/**
 * 
 */
package skewreduce.framework.planner.axis;

import skewreduce.lib.Histogram;
import skewreduce.lib.ITuple;
import skewreduce.lib.KahanSum;
import skewreduce.lib.Partition;

public class Axis implements Comparable<Axis> {
	protected final int index; // axis index
	protected float mv;  // minimum value along the axis
	protected float Mv;  // maximum value along the axis
	
	protected float minV;
	protected float maxV;
	protected final KahanSum s2 = new KahanSum();
	protected final KahanSum s = new KahanSum();
	protected Histogram h;
	protected int n;
	protected final Partition partition;

	public Axis(Partition p,int index) {
		partition = p;
		this.index = index;
	}
	
	public void setBound(float m,float M) {
		mv = m; Mv = M;
	}

	public void setHistogram(int numBuckets) {
		h = new Histogram(mv,Mv,numBuckets);
	}
	
	public void setHistogram(float bucketWidth) {
		h = new Histogram(mv,Mv,bucketWidth);
	}
	
	public void update(ITuple t) {
		float v = t.getFloat(index);
		s.add(v);
		s2.add(v*v);
		if ( h != null ) h.add(t, index);
		if ( v < minV ) minV = v;
		if ( v > maxV ) maxV = v;
		++n;
	}
	
	public double getAverage() {
		return s.value() / n;
	}
	
	public double getStdev() {
		double avg = getAverage();
		return Math.sqrt(s2.value()/n - avg*avg);
	}
	
	public int getNumSample() {
		return n;
	}
	
	public double getMinBound() { return mv; }
	public double getMaxBound() { return Mv; }
	public double getMidPoint() { return (mv+Mv)*0.5; }
	public double getActualMin() { return minV; }
	public double getActualMax() { return maxV; }
	
	public Partition getPartition() { return partition; }
	
	public float getLength() {
		return Mv - mv;
	}
	
	public Histogram getHistogram() {
		return h;
	}

	@Override
	public int compareTo(Axis o) {
		return index - o.index;
	}

	public int getIndex() {
		return index;
	}
}